<?php
/**
 * Created by PhpStorm.
 * Date: 2023/05/18
 * Time: 16:30
 * Desc: 大转盘抽奖逻辑
 */
namespace app\backend\services\lottery;

use App\backend\models\BigWheelLogModel;
use App\backend\models\MemberModel;
use app\backend\services\BigWheelServices;
use App\common\services\BaseServices;
use App\backend\models\ActivityShareModel;
use App\backend\models\BigWheelModel;
use App\backend\models\BigWheelPrizeModel;
use App\frontend\services\BusinessDetailLogServices;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Facades\DB;
use App\backend\services\lottery\LotteryAlgorithm;

class LotteryServices extends BaseServices
{

    const TYPE_ONE = 1;
    const TYPE_TWO = 2;


    /**
     * 次数抽奖--开始
     * 生成次数抽奖记录，并返回抽奖结果记录
     * @return void
     */
    public function numLottery($info, $uid)
    {
        //获取用户抽奖次数
        $num = LotteryServices::getNumByLotteryRules($info, $uid);
        if ($num <= 0) {
            return self::returnError('404005', '暂无抽奖次数');
        }
        $activity_id = $info['activity_id'];
        //次数抽奖流程
        $result = self::numLotterySave($activity_id, $uid);
        if ($result['status'] != 0) {
            return self::returnError($result['status'], $result['msg']);
        }
        return self::returnSuccess('ok', $result['data']);
    }


    /**
     * 积分抽奖
     * 生成次数抽奖记录，并返回抽奖结果记录
     * @param $activity_id
     * @param $uid
     * @param $point_rule
     * @return array|int|null
     */
    public function pointLottery($info, $uid)
    {
        //积分抽奖流程
        //检查条件
        $check_result = self::checkPointLottery($info, $uid);
        if ($check_result['status'] != 0) {
            return self::returnError($check_result['status'], $check_result['msg']);
        }
        $activity_id = $info['activity_id'];
        //抽奖及保存内容
        $result = self::pointLotterySave($activity_id, $uid, $check_result['data']);
        if ($result['status'] != 0) {
            return self::returnError($check_result['status'], $check_result['msg']);
        }
        return self::returnSuccess('ok', $result['data']);
    }


    /**
     * 处理抽奖规则
     * @param $info
     * @param $start_time
     * @param $end_time
     * @param $extra_rules
     * @return void
     */
    public function getLotteryRules($info, &$start_time, &$end_time, &$extra_rules)
    {
        //规则周期
        switch ($info['cycle_rules']) {
            case self::TYPE_ONE:
                $start_time = strtotime(date("Y-m-d 00:00:00"));
                $end_time = strtotime(date("Y-m-d 23:59:59"));
                break;
            case self::TYPE_TWO:
                $start_time = $info['start_time'];
                $end_time = $info['end_time'];
                break;
        }
        //额外次数--抽奖规则
        $extra_rules = BigWheelServices::acticityRules($info['extra_rules']);
    }

    /**
     * 通过抽奖规则获取，抽奖次数
     * 上限次数(0为无上限）
     * 规则周期--1.按天重复    2.活动期间触发一次
     * 1.免费获得（ ）次数
     * 2.分享好友获的1次，上限（ ）次 （0无上限）
     * 3.在商城消费满（ ），获得1次数，上限（ ）次
     * 判断是否可以抽奖，可以则获取抽奖结果。保存。
     * @param $info
     * @param $uid
     * @return int|void
     */
    public function getNumByLotteryRules($info, $uid)
    {
        $lottery_num = 0;
        if (empty($uid) || empty($info['activity_id']) || empty($info['cycle_rules']) || empty($info['extra_rules'])) {
            return $lottery_num;
        }
        //获取规则
        $start_time = 0;
        $end_time = 0;
        $extra_rules = [];
        self::getLotteryRules($info, $start_time, $end_time, $extra_rules);

        //根据规则获取抽奖次数
        $activity_id = $info['activity_id'];
        //免费次数
        $free_num = self::getFreeNum($info['free_num']);
        //分享获取次数
        $share_num = self::getShareNum($uid, $activity_id, $extra_rules, $start_time, $end_time);
        //消费获取次数
        $consume_num = self::getConsumeNum($uid, $extra_rules, $start_time, $end_time);

        //已使用次数
        $used_num = self::getUsedNum($uid, $activity_id, $start_time, $end_time, 1);
//
//        echo '免费获得次数' . $free_num . '<br>';
//        echo '分享获得次数' . $share_num . '<br>';
//        echo '消费获得次数' . $consume_num . '<br>';
//        echo '已使用次数' . $used_num . '<br>';
        $lottery_num = $free_num + $share_num + $consume_num - $used_num;

        return $lottery_num;
    }

    /**
     * 积分抽奖 验证是否可以积分抽奖
     * @param $info
     * @param $uid
     * @return string
     */
    public function checkPointLottery($info, $uid)
    {
        $msg = 'error';
        if (empty($uid) || empty($info['activity_id']) || empty($info['cycle_rules']) || empty($info['extra_rules'])) {
            return self::returnError('401001', $msg);
        }
        //获取规则
        $start_time = 0;
        $end_time = 0;
        $extra_rules = [];
        LotteryServices::getLotteryRules($info, $start_time, $end_time, $extra_rules);
        if (empty($extra_rules['point']) || $extra_rules['point']['is_point'] != self::TYPE_ONE) {
            return self::returnError('401001', '该活动不支持积分兑换');
        }
        $activity_id = $info['activity_id'];
        //积分兑换--最大兑换次数
        $used_point = $extra_rules['point']['point'];
        //限制
        $limit = $extra_rules['point']['num'];
        //积分抽奖次数
        $used_num = self::getUsedNum($uid, $activity_id, $start_time, $end_time, 2);
        if ($limit > 0 && $used_num >= $limit) {
            return self::returnError('401001', '兑换次数已用完');
        }
        //获取用户积分
        $user_point = DB::table(MemberModel::TABLE_NAME)->select(['uid', 'points'])->where(['uid' => $uid])->first();
        if (empty($user_point)) {
            return self::returnError('401001', '请先登录');
        }
        if ($user_point->points < $used_point) {
            return self::returnError('401001', '积分不足');
        }
        return self::returnSuccess('ok', $extra_rules['point']);
    }


    /**
     * 积分抽奖
     * 生成次数抽奖记录，并返回抽奖结果记录
     * @param $activity_id
     * @param $uid
     * @param $point_rule
     * @return array|int|null
     */
    private function pointLotterySave($activity_id, $uid, $point_rule)
    {

        if (empty($uid) || empty($activity_id) || empty($point_rule)) {
            return self::returnError('401001', 'param error');
        }
        try {
            //扣除积分
            $point = $point_rule['point'];
            $info = ['uid' => $uid];
            //扣除积分
            $condition = ['uid' => $uid];
            MemberModel::getInstance()->modifySave($condition, ['points' => new Expression('points - ' . $point)]);
            //积分使用记录
            //增加积分明细
            BusinessDetailLogServices::SaveDetailsLog(Self::TYPE_ONE, 'sub_point_lottery', $point, $info);
            //保存抽奖信息
            $data = [];
            $data['uid'] = $uid;
            $data['use_type'] = self::TYPE_ONE;
            $prize = self::saveLotteryLog($activity_id, $data);
            DB::commit();
            return self::returnSuccess('ok', $prize);
        } catch (Exception $e) {
            DB::rollback();
            return self::returnError('401001', $e->getMessage());
        }

    }

    /**
     * 次数抽奖
     * 生成次数抽奖记录，并返回抽奖结果记录
     * @return void
     */
    private function numLotterySave($activity_id, $uid)
    {
        if (empty($uid) || empty($activity_id)) {
            return self::returnError('401001', 'param error');
        }
        //保存抽奖信息
        $data = [];
        $data['uid'] = $uid;
        $data['use_type'] = self::TYPE_TWO;
        $prize = self::saveLotteryLog($activity_id, $data);
        if (empty($prize)) {
            return self::returnError('401001', 'empty error');
        }
        return self::returnSuccess('ok', $prize);
    }

    /**
     * 获得抽奖结果，并生成抽奖记录
     * @param $activity_id
     * @param $data
     * @return array|int|null
     */
    private function saveLotteryLog($activity_id, $data)
    {
        //获取抽奖结果
        $prize = LotteryServices::getLotteryResults($activity_id);
        //中奖信息['id' => 3,'pid'=>25,'name'=>测试券]
        //未中奖信息['id' => 0,'pid'=>0,'name'=>谢谢参与]

        //并保存抽奖记录
        $data['activity_id'] = $activity_id;
        $data['prize_id'] = $prize['pid'];
        $data['name'] = $prize['name'];
        $data['content'] = $prize['content'];
        $data['status'] = $prize['pid'] > 0 ? 1 : 0;
//        $res = BigWheelLogModel::getInstance()->insertSave($data);
        $res = 1;
        if ($res) {
            return $prize;
        } else {
            return [];
        }
    }

    /**
     * 获取抽奖结果
     * @param $activity_id
     * @return int|void
     */
    private function getLotteryResults($activity_id)
    {
        $prize_num = 0;//未中奖
        if (empty($activity_id)) {
            return $prize_num;
        }
        $prize_list = self::getLotteryInfo($activity_id);
        $Lottery = new LotteryAlgorithm($prize_list, $activity_id);
        //获取抽奖结果
        $prize = $Lottery->get_prize();
        //$prize = $Lottery->get_prize2();
        return $prize;
        //中奖信息['id' => 3,'pid'=>25,'name'=>测试券,'content'=>'']
        //未中奖信息['id' => 0,'pid'=>0,'name'=>谢谢参与,'content'=>'']
    }

    /**
     * 获取免费抽奖次数
     * @param $num
     * @return int
     */
    private function getFreeNum($num)
    {
        return !empty($num) ? $num : 0;
    }

    /**
     * 分享获得次数
     * @param $uid
     * @param $activity_id
     * @param $rules
     * @param $start_time
     * @param $end_time
     * @return int
     */
    private function getShareNum($uid, $activity_id, $rules, $start_time, $end_time)
    {
        $num = 0;
        if (empty($rules) || empty($uid)) return $num;
        if (!empty($rules['share']) && $rules['share']['is_share'] == self::TYPE_ONE) {
            //获取分享-获得次数
            $condition = ['from_id' => $uid, 'activity_id' => $activity_id, 'status' => 1, 'type' => 1];
            $condition[] = ['create_time', '>=', $start_time];
            $condition[] = ['create_time', '<=', $end_time];
            $user_num = ActivityShareModel::getInstance()->getCount($condition);
            //限制
            $limit = $rules['share']['num'];
            $num = $limit == 0 ? $user_num : bccomp($limit, $user_num, 2) ? $user_num : $limit;
        }
        return $num;
    }

    /**
     * 消费获得次数
     * @param $uid
     * @param $rules
     * @param $start_time
     * @param $end_time
     * @return int|void
     */
    private function getConsumeNum($uid, $rules, $start_time, $end_time)
    {
        $num = 0;
        if (empty($rules) || empty($uid)) return $num;
        if (!empty($rules['consume']) && $rules['consume']['is_consume'] == self::TYPE_ONE) {
            //获取消费-获得次数
            $consume_money = $rules['consume']['money'];
            $condition = ['uid' => $uid];
            $condition[] = ['price', '>=', $consume_money];//满足金额
            $condition[] = ['create_time', '>=', $start_time];
            $condition[] = ['create_time', '<=', $end_time];
            $status_in = [2, 3, 4, 5];//订单状态
            $user_num = DB::table('order')->where($condition)->whereIn('status', $status_in)->count();
            //限制
            $limit = $rules['consume']['num'];
            $num = $limit == 0 ? $user_num : bccomp($limit, $user_num, 2) ? $user_num : $limit;
        }
        return $num;
    }

    /**
     * 获得已使用次数
     * @param $uid
     * @param $activity_id
     * @param $start_time
     * @param $end_time
     * @param $use_type
     * @return int
     */
    private function getUsedNum($uid, $activity_id, $start_time, $end_time, $use_type = 1)
    {
        $num = 0;
        if (empty($uid) || empty($activity_id)) return $num;
        //已使用抽奖次数
        $condition = ['uid' => $uid, 'use_type' => $use_type, 'activity_id' => $activity_id];
        $condition[] = ['create_time', '>=', $start_time];
        $condition[] = ['create_time', '<=', $end_time];
        $used_num = BigWheelLogModel::getInstance()->getCount($condition);
        return $used_num;
    }

    /**
     * 处理活动奖品信息
     * @param $activity_id
     * @return array
     */
    private function getLotteryInfo($activity_id)
    {
        $prize_data = [];
        if (empty($activity_id)) {
            return $prize_data;
        }
        $field = ['prize_id', 'prize_name', 'prize_inventory', 'win_chance', 'prize_type', 'prize_content_id', 'prize_content'];
        $prize_list = BigWheelPrizeModel::getInstance()->getList(['activity_id' => $activity_id], $field);
        if (empty($prize_list)) {
            return $prize_data;
        }
        //处理奖品信息
        foreach ($prize_list as $key => $val) {
            $arr = [];
            $arr['id'] = $key + 1;
            $arr['pid'] = $val->prize_id;
            $arr['name'] = $val->prize_name;
            $arr['content'] = $val->prize_content;
            $arr['type'] = $val->prize_type;
            $arr['inventory'] = $val->prize_inventory;
            $arr['chance'] = $val->win_chance;
            $prize_data[] = $arr;
        }
        return $prize_data;
    }
}
